const { body, param, query, validationResult } = require('express-validator');

/**
 * 处理验证结果的中间件
 * 如果有验证错误，返回错误信息
 */
const handleValidationErrors = (req, res, next) => {
  const errors = validationResult(req);
  
  if (!errors.isEmpty()) {
    const errorMessages = errors.array().map(error => ({
      field: error.path || error.param,
      message: error.msg,
      value: error.value
    }));
    
    // 添加日志输出
    console.log(`[VALIDATION_ERROR] ${req.method} ${req.path}:`, errorMessages);
    
    return res.status(400).json({
      success: false,
      message: '输入数据验证失败',
      errors: errorMessages,
      error_code: 'VALIDATION_ERROR'
    });
  }
  
  next();
};

/**
 * 用户注册验证规则
 */
const validateUserRegistration = [
  body('email')
    .isEmail()
    .withMessage('请输入有效的邮箱地址')
    .normalizeEmail()
    .isLength({ max: 255 })
    .withMessage('邮箱地址长度不能超过255个字符'),
    
  body('password')
    .isLength({ min: 8, max: 128 })
    .withMessage('密码长度必须在8-128个字符之间')
    .matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/, 'i')
    .withMessage('密码必须包含至少一个大写字母、一个小写字母、一个数字和一个特殊字符'),
    
  body('username')
    .optional()
    .isLength({ min: 3, max: 50 })
    .withMessage('用户名长度必须在3-50个字符之间')
    .matches(/^[a-zA-Z0-9_]+$/)
    .withMessage('用户名只能包含字母、数字和下划线'),
    
  body('first_name')
    .optional()
    .isLength({ min: 1, max: 50 })
    .withMessage('名字长度必须在1-50个字符之间')
    .matches(/^[\u4e00-\u9fa5a-zA-Z\s]+$/)
    .withMessage('名字只能包含中文、英文字母和空格'),
    
  body('last_name')
    .optional()
    .isLength({ min: 1, max: 50 })
    .withMessage('姓氏长度必须在1-50个字符之间')
    .matches(/^[\u4e00-\u9fa5a-zA-Z\s]+$/)
    .withMessage('姓氏只能包含中文、英文字母和空格'),
    
  body('phone')
    .optional()
    .isMobilePhone('zh-CN')
    .withMessage('请输入有效的中国大陆手机号码'),
    
  body('date_of_birth')
    .optional()
    .isISO8601()
    .withMessage('请输入有效的日期格式 (YYYY-MM-DD)')
    .custom((value) => {
      const birthDate = new Date(value);
      const today = new Date();
      const age = today.getFullYear() - birthDate.getFullYear();
      
      if (age < 13 || age > 120) {
        throw new Error('年龄必须在13-120岁之间');
      }
      
      return true;
    }),
    
  body('gender')
    .optional()
    .isIn(['male', 'female', 'other'])
    .withMessage('性别必须是 male、female 或 other'),
    
  body('preferred_language')
    .optional()
    .isIn(['zh', 'en'])
    .withMessage('首选语言必须是 zh 或 en'),
    
  handleValidationErrors
];

/**
 * 用户登录验证规则
 */
const validateUserLogin = [
  body('email')
    .isEmail()
    .withMessage('请输入有效的邮箱地址')
    .normalizeEmail(),
    
  body('password')
    .notEmpty()
    .withMessage('密码不能为空')
    .isLength({ min: 1, max: 128 })
    .withMessage('密码长度不能超过128个字符'),
    
  body('remember_me')
    .optional()
    .isBoolean()
    .withMessage('记住我选项必须是布尔值'),
    
  handleValidationErrors
];

/**
 * 密码重置请求验证规则
 */
const validatePasswordResetRequest = [
  body('email')
    .isEmail()
    .withMessage('请输入有效的邮箱地址')
    .normalizeEmail(),
    
  handleValidationErrors
];

/**
 * 密码重置验证规则
 */
const validatePasswordReset = [
  body('token')
    .notEmpty()
    .withMessage('重置令牌不能为空')
    .isLength({ min: 32, max: 128 })
    .withMessage('重置令牌格式无效'),
    
  body('new_password')
    .isLength({ min: 8, max: 128 })
    .withMessage('新密码长度必须在8-128个字符之间')
    .matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/, 'i')
    .withMessage('新密码必须包含至少一个大写字母、一个小写字母、一个数字和一个特殊字符'),
    
  handleValidationErrors
];

/**
 * 更改密码验证规则
 */
const validatePasswordChange = [
  body('current_password')
    .notEmpty()
    .withMessage('当前密码不能为空'),
    
  body('new_password')
    .isLength({ min: 8, max: 128 })
    .withMessage('新密码长度必须在8-128个字符之间')
    .matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/, 'i')
    .withMessage('新密码必须包含至少一个大写字母、一个小写字母、一个数字和一个特殊字符')
    .custom((value, { req }) => {
      if (value === req.body.current_password) {
        throw new Error('新密码不能与当前密码相同');
      }
      return true;
    }),
    
  handleValidationErrors
];

/**
 * 用户信息更新验证规则
 */
const validateUserUpdate = [
  body('username')
    .optional()
    .isLength({ min: 3, max: 50 })
    .withMessage('用户名长度必须在3-50个字符之间')
    .matches(/^[a-zA-Z0-9_]+$/)
    .withMessage('用户名只能包含字母、数字和下划线'),
    
  body('first_name')
    .optional()
    .isLength({ min: 1, max: 50 })
    .withMessage('名字长度必须在1-50个字符之间')
    .matches(/^[\u4e00-\u9fa5a-zA-Z\s]+$/)
    .withMessage('名字只能包含中文、英文字母和空格'),
    
  body('last_name')
    .optional()
    .isLength({ min: 1, max: 50 })
    .withMessage('姓氏长度必须在1-50个字符之间')
    .matches(/^[\u4e00-\u9fa5a-zA-Z\s]+$/)
    .withMessage('姓氏只能包含中文、英文字母和空格'),
    
  body('date_of_birth')
    .optional()
    .isISO8601()
    .withMessage('请输入有效的日期格式 (YYYY-MM-DD)')
    .custom((value) => {
      const birthDate = new Date(value);
      const today = new Date();
      const age = today.getFullYear() - birthDate.getFullYear();
      
      if (age < 13 || age > 120) {
        throw new Error('年龄必须在13-120岁之间');
      }
      
      return true;
    }),
    
  body('gender')
    .optional()
    .isIn(['male', 'female', 'other'])
    .withMessage('性别必须是 male、female 或 other'),
    
  body('preferred_language')
    .optional()
    .isIn(['zh', 'en'])
    .withMessage('首选语言必须是 zh 或 en'),
    
  handleValidationErrors
];

/**
 * 邮箱验证码验证规则
 */
const validateEmailVerification = [
  body('verification_code')
    .isLength({ min: 6, max: 6 })
    .withMessage('验证码必须是6位数字')
    .isNumeric()
    .withMessage('验证码只能包含数字'),
    
  handleValidationErrors
];

/**
 * 手机号验证码验证规则
 */
const validatePhoneVerification = [
  body('phone')
    .isMobilePhone('zh-CN')
    .withMessage('请输入有效的中国大陆手机号码'),
    
  body('verification_code')
    .isLength({ min: 6, max: 6 })
    .withMessage('验证码必须是6位数字')
    .isNumeric()
    .withMessage('验证码只能包含数字'),
    
  handleValidationErrors
];

/**
 * 用户ID参数验证
 */
const validateUserId = [
  param('userId')
    .isInt({ min: 1 })
    .withMessage('用户ID必须是正整数'),
    
  handleValidationErrors
];

/**
 * 分页参数验证
 */
const validatePagination = [
  query('page')
    .optional()
    .isInt({ min: 1 })
    .withMessage('页码必须是正整数')
    .toInt(),
    
  query('limit')
    .optional()
    .isInt({ min: 1, max: 100 })
    .withMessage('每页数量必须在1-100之间')
    .toInt(),
    
  query('sort')
    .optional()
    .isIn(['created_at', 'updated_at', 'username', 'email'])
    .withMessage('排序字段无效'),
    
  query('order')
    .optional()
    .isIn(['asc', 'desc'])
    .withMessage('排序方向必须是 asc 或 desc'),
    
  handleValidationErrors
];

/**
 * 搜索参数验证
 */
const validateSearch = [
  query('keyword')
    .optional()
    .isLength({ min: 1, max: 100 })
    .withMessage('搜索关键词长度必须在1-100个字符之间')
    .trim()
    .escape(),
    
  handleValidationErrors
];

/**
 * 文件上传验证
 */
const validateFileUpload = (req, res, next) => {
  if (!req.file) {
    return res.status(400).json({
      success: false,
      message: '请选择要上传的文件',
      error_code: 'NO_FILE'
    });
  }
  
  // 检查文件类型
  const allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
  if (!allowedMimeTypes.includes(req.file.mimetype)) {
    return res.status(400).json({
      success: false,
      message: '不支持的文件类型，只允许上传 JPEG、PNG、GIF、WebP 格式的图片',
      error_code: 'INVALID_FILE_TYPE'
    });
  }
  
  // 检查文件大小 (5MB)
  const maxSize = 5 * 1024 * 1024;
  if (req.file.size > maxSize) {
    return res.status(400).json({
      success: false,
      message: '文件大小不能超过5MB',
      error_code: 'FILE_TOO_LARGE'
    });
  }
  
  next();
};

/**
 * 自定义验证器：检查邮箱是否已存在
 */
const checkEmailExists = async (email) => {
  const User = require('../models/User');
  const existingUser = await User.findByEmail(email);
  if (existingUser) {
    throw new Error('该邮箱已被注册');
  }
  return true;
};

/**
 * 自定义验证器：检查用户名是否已存在
 */
const checkUsernameExists = async (username) => {
  const User = require('../models/User');
  const db = require('../config/database');
  const [rows] = await db.execute('SELECT user_id FROM users WHERE username = ? AND is_active = true', [username]);
  if (rows.length > 0) {
    throw new Error('该用户名已被使用');
  }
  return true;
};

/**
 * 自定义验证器：检查手机号是否已存在
 */
const checkPhoneExists = async (phone) => {
  const User = require('../models/User');
  const existingUser = await User.findByPhone(phone);
  if (existingUser) {
    throw new Error('该手机号已被注册');
  }
  return true;
};

module.exports = {
  handleValidationErrors,
  validateUserRegistration,
  validateUserLogin,
  validatePasswordResetRequest,
  validatePasswordReset,
  validatePasswordChange,
  validateUserUpdate,
  validateEmailVerification,
  validatePhoneVerification,
  validateUserId,
  validatePagination,
  validateSearch,
  validateFileUpload,
  checkEmailExists,
  checkUsernameExists,
  checkPhoneExists
};